import axios from 'axios';
import errCodes from './errCodes'
import { showDialog } from 'vant';
import { errorToast } from './toast';
import { useUserStore } from '@/stores/user'
import { removeToken, removeRefreshToken, getToken } from '@/utils/storage'
import type { AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';

// 是否显示重新登录
const isRelogin = { show: false, promise: Promise.resolve({ statusCode: 200 }) }

const instance: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 10000 // 10秒超时，根据项目自定义
});


/* 请求拦截器 */
instance.interceptors.request.use(
  (config: any) => {
    const requestStore = useUserStore()

    requestStore.loading = true

    const token = getToken()

    if (!('Authorization' in config.headers) && token) {
      config.headers.Authorization = `Bearer ${token}`
    }

    return config
  },
  (error: AxiosError) => {
    // 错误提示
    return Promise.reject(error);
  }
);

/* 响应拦截器 */
instance.interceptors.response.use(
  (response: AxiosResponse<Result>): any => {
    const responseStore = useUserStore()

    responseStore.loading = false

    const { statusCode, message } = response.data;

    if (statusCode === 200) {
      return response.data
    } else {
      errorToast(message);
    }
    return Promise.reject(new Error(message))
  },
  async (error: any) => {
    const a = useUserStore()

    a.loading = false
    const { statusCode, message } = error.response.data

    if (statusCode !== 200) {
      let textMsg = message
      if (errCodes[message]) {
        textMsg = errCodes[message]
      }
      if (
        statusCode === 401 &&
        error.config?.url &&
        error.config?.url.indexOf('/user/get_new_token') >= 0
      ) {
        showDialog({
          title: '系统提示',
          message: '登录状态已过期，请重新登录。',
          theme: 'round-button',
          confirmButtonText: '重新登录',
        }).then(() => {
          removeToken()
          removeRefreshToken()
          location.href = '/login'
        });
        return
      } else if (statusCode === 401) {
        const store = useUserStore()

        let res = null
        if (!isRelogin.show) {
          isRelogin.show = true

          isRelogin.promise = store.getNewAccessToken()

          res = await isRelogin.promise

          if (res && res.statusCode === 200) {
            isRelogin.show = false
            const config = error.config
            delete config.headers.Authorization
            return await instance.request(config)
          }
        } else {
          res = await isRelogin.promise
        }
      } else if (statusCode === 403) {

        showDialog({
          title: '系统提示',
          message: '当前用户没有操作权限，请重新登录。',
          theme: 'round-button',
          confirmButtonText: '重新登录',
        }).then(() => {
          removeToken()
          removeRefreshToken()
          location.href = '/login'
        });
      } else {
        errorToast(message);
      }

      return Promise.reject(new Error(message))
    }

    return Promise.reject(error)
  }
);

// 分页数据类型
export type PaginationType<T = any> = {
  records: T[];
  current: number;
  size: number;
  total: number;
};

const get = <T = any>(url: string, params?: object, config?: AxiosRequestConfig): Promise<Result<T>> => {
  return instance.get(url, {
    ...config,
    params
  });
};

const post = <T = any>(url: string, data?: object, config?: AxiosRequestConfig): Promise<Result<T>> => {
  return instance.post(url, data, config);
};

const put = <T>(url: string, data?: object, config?: AxiosRequestConfig): Promise<T> => {
  return instance.put(url, data, config)
}

const getList = <T = any>(
  url: string,
  params?: object,
  config?: AxiosRequestConfig
): Promise<PaginationType<T>> => {
  return instance.get(url, {
    ...config,
    params
  });
};

const postList = <T = any>(
  url: string,
  data?: object,
  config?: AxiosRequestConfig
): Promise<PaginationType<T>> => {
  return instance.post(url, data, config);
};

/*服务器返回数据类型 */
export type Result<T = any> = {
  statusCode: number
  message: string
  data: T
}

/* 导出封装的请求方法 */
export const http = {
  get,
  post,
  put,
  getList,
  postList
};